前幾天我們已經學會了如何存資料、做運算,以及用條件判斷與迴圈來控制流程。不過,如果程式越寫越大,一直重複貼相似的程式碼,不僅難以維護,也容易出錯。這時候,就需要用到 函式(Function)。
函式的角色就像是一個「工具」或「機器」:
在日常生活中:
今天會學到:
return —— 如何讓函式把結果交回來。*args、**kwargs。return,或使用錯誤的預設值。學會函式之後,程式就能更有架構,並且開始具備「模組化思維」,這也是邁向大型專案開發的重要基礎。
# 定義一個函式(Function):加總兩數
def add(a, b):             # a, b 是[參數]
    result = a + b
    return result          # 傳出[回傳值]
# 呼叫函式,給予[引數]
print(add(3, 5))           # 輸出:8

重點記憶:
def定義函式,return把資料傳出
| 名稱 | 定義位置 | 舉例 | 
|---|---|---|
| 參數 | 函式「定義」時 | def add(a, b) | 
| 引數 | 函式「呼叫」時 | add(3, 5) | 
returndef square(x):         # x 是[參數]
    return x * x       # 傳出[回傳值]
y = square(4)          # y 得到 16
print(y)               # 輸出:16
❗ 如果沒寫
return,會默認回傳None
*args、**kwargs)def greet(name="小明"):
    print(f"哈囉,{name}!")
greet("阿華")    # 傳入引數
greet()          # 使用預設值
-- 若有印引數,則程式會採用引數阿華,若無,則使用預設的小明
*argsdef total(*args):    # args 會收集所有位置引數成為 tuple
    return sum(args)
print(total(1, 2, 3))    # 輸出:6
print(total(1, 2, 3, 4, 5))    # 輸出:15
**kwargsdef profile(**kwargs):   # kwargs 會收集所有關鍵字引數成為 dict
    for k, v in kwargs.items():
        print(f"{k}:{v}")
profile(name="小美", age=18)
# 輸出:
# name:小美
# age:18
returndef bad_add(a, b):
    result = a + b
    # 忘記寫 return
print(bad_add(3,5)) # 輸出 None,如圖1
def good_add(a, b):
    result = a + b
    return result    # 正確回傳結果
print(good_add(3, 5))  # 輸出 8,如圖2
-- 圖1: --
--
圖2:
錯誤寫法:
def bad_append(item, target=[]):  #  所有呼叫都用同一個 list
    target.append(item)
    return target
print(bad_append(1))    # [1]
print(bad_append(2))    # [1, 2] ← 上次的結果還在!
正確寫法:
def good_append(item, target=None):
    if target is None:
        target = []     # 每次都建立新的 list
    target.append(item)
    return target
print(good_append(1))    # [1]
print(good_append(2))    # [2] ← 正確!
def calculate(a, b):
    return a + b, a - b, a * b    # 回傳 tuple
# 接收多個回傳值
add_result, sub_result, mul_result = calculate(10, 3)
print(f"加:{add_result}, 減:{sub_result}, 乘:{mul_result}")
| 語法 | 意義 | 
|---|---|
| def 函式名(參數): | 定義函式 | 
| return 值 | 傳出資料 | 
| 函式名(引數) | 呼叫函式 | 
| 參數 = 預設值 | 預設參數值 | 
| *args | 接收多個位置引數(tuple) | 
| **kwargs | 接收多個關鍵字引數(dict) | 
def add(x, y):
    """加法運算"""
    return x + y
def subtract(x, y):
    """減法運算"""
    return x - y
def multiply(x, y):
    """乘法運算"""
    return x * y
def divide(x, y=1):
    """除法運算,預設除以 1"""
    if y == 0:
        return "除以零錯誤"
    return x / y
def show_all(x, y):
    """展示所有運算結果"""
    print(f"加法:{add(x, y)}")
    print(f"減法:{subtract(x, y)}")
    print(f"乘法:{multiply(x, y)}")
    print(f"除法:{divide(x, y)}")
# 測試
show_all(10, 5)
x = 100    # 全域變數
def test_scope():
    x = 50    # 區域變數,只在函式內有效
    print(f"函式內的 x:{x}")
test_scope()    # 輸出:函式內的 x:50
print(f"函式外的 x:{x}")    # 輸出:函式外的 x:100
# 一般函式
def square(x):
    return x ** 2
# Lambda 函式(匿名函式)
square_lambda = lambda x: x ** 2
print(square(5))         # 25
print(square_lambda(5))  # 25
# 常用於排序、過濾
numbers = [3, 1, 4, 1, 5]
sorted_nums = sorted(numbers, key=lambda x: -x)  # 降序排列
print(sorted_nums)  # [5, 4, 3, 1, 1]
greet(name):輸出 你好,{name}!
even_or_odd(n):判斷奇偶,回傳 "偶數" 或 "奇數"calc(*nums):可接受任意數量數字,回傳 (總和, 平均)
# 題目 1
def greet(name):
    """打招呼函式"""
    print(f"你好,{name}!")
# 測試
greet("Jr")    # 輸出:你好,Jr!
# 題目 2
def even_or_odd(n):
    
    if n % 2 == 0:
        return "偶數"
    else:
        return "奇數"
# 測試
print(even_or_odd(4))    # 輸出:偶數
print(even_or_odd(7))    # 輸出:奇數
# 題目 3
def calc(*nums):
    """計算總和與平均
    
    參數:
        *nums: 任意數量的數字
        
    回傳:
        tuple: (總和, 平均)
    """
    if not nums:    # 如果沒有傳入數字
        return 0, 0
    
    total = sum(nums)
    average = total / len(nums)
    return total, average
# 測試
print(calc(1, 2, 3, 4, 5))    # 輸出:(15, 3.0)
print(calc(10, 20))           # 輸出:(30, 15.0)
def safe_divide(x, y):
    """安全的除法運算
    
    參數:
        x (float): 被除數
        y (float): 除數
        
    回傳:
        float 或 str: 運算結果或錯誤訊息
    """
    try:
        if y == 0:
            raise ZeroDivisionError("不能除以零")
        return x / y
    except ZeroDivisionError as e:
        return f"錯誤:{e}"
    except Exception as e:
        return f"未知錯誤:{e}"
# 測試
print(safe_divide(10, 2))    # 5.0
print(safe_divide(10, 0))    # 錯誤:不能除以零